package com.cxyd.modules.wcs.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cxyd.common.constant.RcsConstants;
import com.cxyd.common.constant.WcsConstants;
import com.cxyd.common.service.impl.CrudServiceImpl;
import com.cxyd.modules.api.dto.RcsResultYF;
import com.cxyd.modules.log.service.SysLogWorkService;
import com.cxyd.modules.wcs.dao.AgvCallbackYfDao;
import com.cxyd.modules.wcs.dto.AgvCallbackYfDTO;
import com.cxyd.modules.wcs.entity.AgvCallbackYfEntity;
import com.cxyd.modules.wcs.entity.AgvTrkYfEntity;
import com.cxyd.modules.wcs.entity.PostWmsEntity;
import com.cxyd.modules.wcs.entity.TrkEntity;
import com.cxyd.modules.wcs.service.AgvCallbackYfService;
import com.cxyd.modules.wcs.service.AgvTrkYfService;
import com.cxyd.modules.wcs.service.PostWmsService;
import com.cxyd.modules.wcs.service.TrkService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.Map;

@Service
public class AgvCallbackYfServiceImpl extends CrudServiceImpl<AgvCallbackYfDao, AgvCallbackYfEntity, AgvCallbackYfDTO> implements AgvCallbackYfService {
    @Resource
    private AgvTrkYfService yFTrkService;
    @Resource
    private TrkService trkService;
    @Resource
    private PostWmsService postWmsService;
    @Resource
    private SysLogWorkService logWorkService;

    @Override
    public QueryWrapper<AgvCallbackYfEntity> getWrapper(Map<String, Object> params) {
        return null;
    }

    @Override
    public void save(AgvCallbackYfDTO dto) {
        AgvCallbackYfEntity entity = new AgvCallbackYfEntity();
        entity.setTaskCode(dto.getTask_code());
        entity.setTaskType(dto.getTask_type());
        entity.setFrom(dto.getFrom());
        entity.setTo(dto.getTo());
        entity.setAdditiveInfo(dto.getAdditive_info());
        entity.setRemark(dto.getRemark());
        entity.setRequestType(dto.getRequest_type());
        entity.setContainerCode(dto.getContainer_code());
        baseDao.saveToDatabase(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RcsResultYF requestHandle(AgvCallbackYfDTO dto) {
        String workName = "[流程-4]执行通知-YF";
        String workProc = "AgvCallbackYfServiceImpl.requestHandle";
//        1.对json报文进行解析
        String taskCode = dto.getTask_code();
        int reqTyp = dto.getRequest_type();
//        根据taskCode获取任务信息
        AgvTrkYfEntity yfTask = yFTrkService.getAgvTryByTaskCode(taskCode);
        if (yfTask == null) {
            String pCode = "requestHandle_001";
            String pMsg = "任务单[" + taskCode + "]无执行任务!";
            logWorkService.workLogging(workName, taskCode, pCode,
                    pMsg, null, workProc, "WCS", 0);
            return new RcsResultYF().error(false, pMsg);
        }
//      1.AGV料箱取申请(可能需要任务继续)
        if (RcsConstants.AGV_REQ_GET == reqTyp) {
//            1.1.更新搬送任务状态
            agvReqGet(yfTask);
        }
//      2.AGV料箱放申请(可能需要任务继续)
        if (RcsConstants.AGV_REQ_PUT == reqTyp) {
//            1.1.更新搬送任务状态
            agvReqPut(yfTask);
        }
//      3.AGV料箱取完成
        if (RcsConstants.AGV_GET_DONE == reqTyp) {
//            1.1.更新搬送任务状态
            agvGetDone(yfTask);
        }
//      4.AGV料箱放完成
        if (RcsConstants.AGV_PUT_DONE == reqTyp) {
//            1.1.更新搬送任务状态
            agvPutDone(yfTask);
        }
        return new RcsResultYF().success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RcsResultYF completeHandle(AgvCallbackYfDTO dto) {
        String workName = "[YF_AGV]完成通知-YF";
        String workProc = "AgvCallbackYfServiceImpl.completeHandle";
//        1.对json报文进行解析(获取reqCode,taskCode,robotCode,method,currentPositionCode)
        String taskCode = dto.getTask_code();
        String completed = dto.getIscompleted();

//        根据taskCode获取任务信息
        AgvTrkYfEntity yfTask = yFTrkService.getAgvTryByTaskCode(taskCode);
        if (yfTask == null) {
            String pCode = "completeHandle_001";
            String pMsg = "任务单[" + taskCode + "]无执行任务!";
            logWorkService.workLogging(workName, taskCode, pCode,
                    pMsg, null, workProc, WcsConstants.WCS_USER_NAME, 10L);
            return new RcsResultYF().error(false, pMsg);
        }
//        处理完成任务
        agvTaskDone(yfTask, completed);
        return new RcsResultYF().success();
    }

    /***
     * 请求取货
     * @param task
     */
    private void agvReqGet(AgvTrkYfEntity task) {
//        通知wms料箱已下架等
        String workName = "[流程-4]取托盘申请-YF";
        String workProc = "AgvCallbackYfServiceImpl.agvReqGet";
        String pCode = WcsConstants.PROC_CODE_SUCCESS;
        String pMsg = "托盘[" + task.getContainerCode() + "]请求取货!";
        Instant start = Instant.now();
//        取放时通知线体完成信号
//        task.setStatus(RcsConstants.TASK_STATUS_GET);//作业取申请
        task.setUpdater(WcsConstants.WCS_USER_ID);
        task.setUpdateDate(new Date());
        yFTrkService.updateById(task);
//      通过trk_id找到设备任务并更新其状态
        TrkEntity trkEntity = trkService.selectById(task.getTrkId());

//        更新wcs_trk任务为执行中
        trkEntity.setTrkSt(WcsConstants.TRK_STATUS_RUNNING);
        trkEntity.setComments(pMsg);
        trkEntity.setUpdateDate(new Date());
        trkService.updateById(trkEntity);
        Instant end = Instant.now();
        Duration times = Duration.between(start, end);
//        记录日志
        logWorkService.workLogging(workName, task.getContainerCode(), pCode,
                pMsg, null, workProc, WcsConstants.WCS_USER_NAME, times.toMillis());
    }

    /***
     * 取货完成
     * @param task
     */
    private void agvGetDone(AgvTrkYfEntity task) {
//        通知wms料箱已下架等
        String workName = "[流程-4]取托盘完成-YF";
        String workProc = "AgvCallbackYfServiceImpl.agvGetDone";
        String pCode = WcsConstants.PROC_CODE_SUCCESS;
        String pMsg = "托盘[" + task.getContainerCode() + "]取货完成!";
        Instant start = Instant.now();
//        取放时通知线体完成信号
//        task.setStatus(RcsConstants.TASK_STATUS_GET_DONE);//作业取申请
        task.setUpdater(WcsConstants.WCS_USER_ID);
        task.setUpdateDate(new Date());
        yFTrkService.updateById(task);
//      通过trk_id找到设备任务并更新其状态
        TrkEntity trkEntity = trkService.selectById(task.getTrkId());

//        更新wcs_trk任务为执行中
        trkEntity.setTrkSt(WcsConstants.TRK_STATUS_RUNNING);
        trkEntity.setComments(pMsg);
        trkEntity.setUpdateDate(new Date());
        trkService.updateById(trkEntity);
        Instant end = Instant.now();
        Duration times = Duration.between(start, end);
//        记录日志
        logWorkService.workLogging(workName, task.getContainerCode(), pCode,
                pMsg, null, workProc, WcsConstants.WCS_USER_NAME, times.toMillis());
    }

    /***
     * 请求放货
     * @param task
     */
    private void agvReqPut(AgvTrkYfEntity task) {
//        通知wms料箱已下架等
        String workName = "[流程-4]放托盘申请-YF";
        String workProc = "AgvCallbackYfServiceImpl.agvReqPut";
        String pCode = WcsConstants.PROC_CODE_SUCCESS;
        String pMsg = "托盘[" + task.getContainerCode() + "]请求放货!";
        Instant start = Instant.now();
//        取放时通知线体完成信号
//        task.setStatus(RcsConstants.TASK_STATUS_PUT);//作业取申请
        task.setUpdater(WcsConstants.WCS_USER_ID);
        task.setUpdateDate(new Date());
        yFTrkService.updateById(task);
//      通过trk_id找到设备任务并更新其状态
        TrkEntity trkEntity = trkService.selectById(task.getTrkId());

//        更新wcs_trk任务为执行中
        trkEntity.setTrkSt(WcsConstants.TRK_STATUS_RUNNING);
        trkEntity.setComments(pMsg);
        trkEntity.setUpdateDate(new Date());
        trkService.updateById(trkEntity);
        Instant end = Instant.now();
        Duration times = Duration.between(start, end);
//        记录日志
        logWorkService.workLogging(workName, task.getContainerCode(), pCode,
                pMsg, null, workProc, WcsConstants.WCS_USER_NAME, times.toMillis());
    }

    /***
     * 放货完成
     * @param task
     */
    private void agvPutDone(AgvTrkYfEntity task) {
//        通知wms料箱已下架等
        String workName = "[流程-4]放托盘完成-YF";
        String workProc = "AgvCallbackYfServiceImpl.agvPutDone";
        String pCode = WcsConstants.PROC_CODE_SUCCESS;
        String pMsg = "托盘[" + task.getContainerCode() + "]放货完成!";
        Instant start = Instant.now();
//        取放时通知线体完成信号
//        task.setStatus(RcsConstants.TASK_STATUS_PUT_DONE);//作业取申请
        task.setUpdater(WcsConstants.WCS_USER_ID);
        task.setUpdateDate(new Date());
        yFTrkService.updateById(task);
//      通过trk_id找到设备任务并更新其状态
        TrkEntity trkEntity = trkService.selectById(task.getTrkId());

//        更新wcs_trk任务为执行中
        trkEntity.setTrkSt(WcsConstants.TRK_STATUS_RUNNING);
        trkEntity.setComments(pMsg);
        trkEntity.setUpdateDate(new Date());
        trkService.updateById(trkEntity);
        Instant end = Instant.now();
        Duration times = Duration.between(start, end);
//        记录日志
        logWorkService.workLogging(workName, task.getContainerCode(), pCode,
                pMsg, null, workProc, WcsConstants.WCS_USER_NAME, times.toMillis());
    }

    /***
     * 任务完成
     * @param task
     */
    private void agvTaskDone(AgvTrkYfEntity task, String completed) {
//        通知wms料箱任务已完成
        String workName = "[流程-5]任务完成-YF";
        String workProc = "AgvCallbackYfServiceImpl.agvTaskDone";
        String pCode = WcsConstants.PROC_CODE_SUCCESS;
        String pMsg = "托盘[" + task.getContainerCode() + "]搬送任务完成!";
        Instant start = Instant.now();
        if (!RcsConstants.AGV_COMPLETED.equals(completed)) {
            task.setRemark("任务完成失败!异常码[" + completed + "]");
            task.setUpdater(WcsConstants.WCS_USER_ID);
            task.setUpdateDate(new Date());
            yFTrkService.updateById(task);
            return;
        }
//        task.setStatus(RcsConstants.TASK_STATUS_DONE);//作业完成上报
        task.setUpdater(WcsConstants.WCS_USER_ID);
        task.setUpdateDate(new Date());
        yFTrkService.updateById(task);
//      通过trk_id找到设备任务并更新其状态
        TrkEntity wcsTrk = trkService.selectById(task.getTrkId());

//        更新wcs_trk任务为执行中
        wcsTrk.setTrkSt(WcsConstants.TRK_STATUS_DONE);
        wcsTrk.setComments(pMsg);
        wcsTrk.setUpdateDate(new Date());
        trkService.updateById(wcsTrk);
//        完成信息上报至WMS
        PostWmsEntity postWms = new PostWmsEntity();
        postWms.setRequestPk(wcsTrk.getRequestPk());
        postWms.setContNo(wcsTrk.getContNo());
        postWms.setCurPos(wcsTrk.getToPos());
//        类型为[完成]
        postWms.setNoticeType(WcsConstants.POST_TYPE_DONE);
        postWms.setCode(pCode);
        postWms.setResult(pMsg);
        postWms.setPostSt(WcsConstants.POST_STATUS_START);
        postWms.setCreator(WcsConstants.WCS_USER_ID);
        postWms.setUpdateDate(new Date());
        postWmsService.insert(postWms);
//        数据处理完成后将agv_trk_yf数据转移(不在此处进行数据转移)
        Instant end = Instant.now();
        Duration times = Duration.between(start, end);
//        记录日志
        logWorkService.workLogging(workName, task.getContainerCode(), pCode,
                pMsg, null, workProc, WcsConstants.WCS_USER_NAME, times.toMillis());
    }
}
